﻿/**
 *
 * speaker.c
 *
 *  Created on: 2019-12-03
 *      Author: chenshisheng
 */

#include "speaker.h"
#include "serial.h"
#include "hw.h"
#include "ctimer.h"

#define _SERIAL Serial_5

#define VOLUME 26
#define VOLUME_MIN 0
#define VOLUME_MAX 30

static Ctimer_t _timer;

static void _OnTimeout(int data);

void Speaker_Init(void)
{
    Serial_IoCtl(_SERIAL, Serial_Ctl_RxCmd, DISABLE);
    Speaker_Speak(1);
}

static uint8_t _CalcChecksum(const void *data, unsigned int size)
{
    uint8_t checksum;
    const uint8_t *vdata;
    unsigned int i;

    checksum = 0;
    vdata = data;
    for(i = 0; i < size; i++)
    {
        checksum += vdata[i];
    }

    return checksum;
}

static void _OnTimeout(int data)
{
    HW_Config(HW_Out_SpeakerEn, HW_State_Inactive);
}

static void _SendFrame(uint8_t cmd, const void *data, uint8_t size)
{
    uint8_t frame[size + 4];

    frame[0] = 0xaa;
    frame[1] = cmd;
    frame[2] = size;
    memcpy(&frame[3], data, size);
    frame[sizeof(frame) - 1] = _CalcChecksum(frame, sizeof(frame) - 1);
    Serial_Send(_SERIAL, frame, sizeof(frame));
}

void Speaker_Speak(int song)
{
    uint16_t data;
    uint8_t buf[2];

    HW_Config(HW_Out_SpeakerEn, HW_State_Active);
    HAL_Delay(50);

    // 设置音量
    buf[0] = VOLUME;
    _SendFrame(0x13, buf, 1);
    HAL_Delay(20);

    data = (uint16_t)song;
    buf[0] = (uint8_t)(data >> 8);
    buf[1] = (uint8_t)data;
    _SendFrame(0x07, buf, 2);

    Ctimer_Start(&_timer, 5 * CTIMER_TICK_SECOND, _OnTimeout, CTIMER_FLAG_ONCE, 0);
    debug("Speaker: 0000%d.mp3\n", song);
}

void Speaker_SpeakAfter(int song)
{
    MsgQueue_Send(MsgQueue_Id_Speak, &song, sizeof(song));
}

int Speaker_SpeakCmd(Stream_t *stream, int argc, char *argv[])
{
    int song;

    if(argc < 2)
    {
        song = 1;
    }
    else
    {
        song = atoi(argv[1]);
    }

    chprintf(stream, "Playing sound %d ...\n", song);
    Speaker_Speak(song);

    return 0;
}

void Speaker_OnSpeak(const MsgQueue_Msg_t *msg)
{
    int song;

    song = *((int *)msg->data);
    Speaker_Speak(song);
}
